using System.Data;
using System.Data.OleDb;
using System.Xml;
using Chaotic.DataBase.DataAccess;
using Chaotic.DataBase.DataAccess.Entity;

namespace Chaotic.DataBase.OLEDBAccess;

public class OledbDataAccess : AbstractDataAccess
{
	private readonly OleDbConnection _mDbConnection;

	private OleDbTransaction? _trans;

	public override DatabaseType DatabaseType => DatabaseType.OleDBSupported;

	public override IDbConnection DbConnection => _mDbConnection;

	public OledbDataAccess(string connectionString)
	{
		_mDbConnection = new OleDbConnection(connectionString);
	}

	public override IDbTransaction? BeginTransaction()
	{
		_trans = _mDbConnection.BeginTransaction();
		return _trans;
	}

	public override int ExecuteNonQuery(CommandType commandType, string? commandText, QueryParameterCollection commandParameters, DataRow row, SqlStruct sqlStruct)
	{
		int tmpValue = 0;
		LogOutPut(delegate
		{
			OleDbCommand oleDbCommand = new OleDbCommand();
			if (sqlStruct == null)
			{
				PrepareCommand(oleDbCommand, commandType, commandText, commandParameters);
			}
			else
			{
				for (int i = 0; i < sqlStruct.ParamFields.Length; i++)
				{
					if (sqlStruct.ParamFields[i].ParamName.IndexOf('_') != 1)
					{
						commandParameters.Add(sqlStruct.ParamFields[i].ParamName, row[sqlStruct.ParamFields[i].FieldName]);
					}
					else
					{
						commandParameters.Add(sqlStruct.ParamFields[i].ParamName, row[sqlStruct.ParamFields[i].FieldName, DataRowVersion.Original]);
					}
				}
				PrepareCommand(oleDbCommand, CommandType.Text, sqlStruct.SqlString, commandParameters);
			}
			tmpValue = oleDbCommand.ExecuteNonQuery();
			oleDbCommand.Parameters.Clear();
			return tmpValue;
		}, "ExecuteNonQuery", commandText, commandParameters);
		return tmpValue;
	}

	public override DataSet? ExecuteDataset(CommandType commandType, string? commandText, QueryParameterCollection commandParameters, DataSet? ds, string tableName)
	{
		LogOutPut(delegate
		{
			OleDbCommand oleDbCommand = new OleDbCommand();
			PrepareCommand(oleDbCommand, commandType, commandText, commandParameters);
			OleDbDataAdapter oleDbDataAdapter = new OleDbDataAdapter(oleDbCommand);
			if (object.Equals(tableName, null) || tableName.Length < 1)
			{
				oleDbDataAdapter.Fill(ds);
			}
			else
			{
				oleDbDataAdapter.Fill(ds, tableName);
			}
			oleDbCommand.Parameters.Clear();
			return (ds != null && ds.Tables.Count > 0) ? ds.Tables[0].Rows.Count : 0;
		}, "ExecuteDataset", commandText, commandParameters);
		return ds;
	}

	public override DataSet? ExecuteDataset(string? commandText, QueryParameterCollection commandParameters, DataSet? ds, int startRecord, int maxRecords, string tableName)
	{
		LogOutPut(delegate
		{
			OleDbCommand oleDbCommand = new OleDbCommand();
			PrepareCommand(oleDbCommand, CommandType.Text, commandText, commandParameters);
			OleDbDataAdapter oleDbDataAdapter = new OleDbDataAdapter(oleDbCommand);
			if (object.Equals(tableName, null) || tableName.Trim() == string.Empty)
			{
				oleDbDataAdapter.Fill(ds);
			}
			else
			{
				oleDbDataAdapter.Fill(ds, startRecord, maxRecords, tableName);
			}
			oleDbCommand.Parameters.Clear();
			return (ds != null && ds.Tables.Count > 0) ? ds.Tables[0].Rows.Count : 0;
		}, "ExecuteDataset", commandText, commandParameters);
		return ds;
	}

	public override IDataReader ExecuteReader(CommandType commandType, string? commandText, QueryParameterCollection commandParameters)
	{
		IDataReader dr = null;
		LogOutPut(delegate
		{
			OleDbCommand oleDbCommand = new OleDbCommand();
			PrepareCommand(oleDbCommand, commandType, commandText, commandParameters);
			dr = oleDbCommand.ExecuteReader();
			oleDbCommand.Parameters.Clear();
			return -1;
		}, "ExecuteReader", commandText, commandParameters);
		return dr;
	}

	public override object? ExecuteScalar(CommandType commandType, string? commandText, QueryParameterCollection commandParameters)
	{
		object? tmpValue = null;
		LogOutPut(delegate
		{
			OleDbCommand oleDbCommand = new OleDbCommand();
			PrepareCommand(oleDbCommand, commandType, commandText, commandParameters);
			tmpValue = oleDbCommand.ExecuteScalar();
			oleDbCommand.Parameters.Clear();
			return -1;
		}, "ExecuteScalar", commandText, commandParameters);
		return tmpValue;
	}

	public override XmlReader ExecuteXmlReader(CommandType commandType, string? commandText, QueryParameterCollection commandParameters)
	{
		return null;
	}

	private void PrepareCommand(OleDbCommand cmd, CommandType commandType, string? commandText, QueryParameterCollection commandParameters)
	{
		commandText = commandText.Replace(":", "@");
		cmd.CommandType = commandType;
		cmd.CommandText = commandText;
		cmd.Connection = _mDbConnection;
		cmd.Transaction = _trans;
		if (commandParameters != null && commandParameters.Count > 0)
		{
			for (int i = 0; i < commandParameters.Count; i++)
			{
				cmd.Parameters.AddWithValue(commandParameters[i].ParameterName, commandParameters[i].Value);
				cmd.Parameters[i].Direction = commandParameters[i].Direction;
			}
		}
	}

	public override void FillingTables(List<TableInfo>? info)
	{
		DataTable schema = _mDbConnection.GetSchema("Tables");
		info.AddRange(from DataRow row in schema.Rows
			select new TableInfo
			{
				TableName = row["TABLE_NAME"].ToString()
			});
	}

	public override void FillingColumns(List<ColumnInfo> info)
	{
		DataTable schema = _mDbConnection.GetSchema("Columns");
		DataTable schema2 = _mDbConnection.GetSchema("DataTypes");
		foreach (DataRow row in schema.Rows)
		{
			string typeName;
			string length;
			if (string.IsNullOrEmpty(row["CHARACTER_MAXIMUM_LENGTH"].ToString()))
			{
				DataRow[] array = schema2.Select(string.Format("NativeDataType = {0} and ColumnSize = {1}", row["DATA_TYPE"], row["NUMERIC_PRECISION"]));
				typeName = array[0]["TypeName"].ToString();
				length = row["NUMERIC_PRECISION"].ToString();
			}
			else
			{
				DataRow[] array2 = schema2.Select(string.Format("NativeDataType = {0} and ColumnSize = {1}", row["DATA_TYPE"], row["CHARACTER_MAXIMUM_LENGTH"]));
				typeName = array2[0]["TypeName"].ToString();
				length = row["CHARACTER_MAXIMUM_LENGTH"].ToString();
			}
			info.Add(new ColumnInfo
			{
				TableName = row["TABLE_NAME"].ToString(),
				ColumnName = row["COLUMN_NAME"].ToString(),
				ColumnIndex = Convert.ToInt32(row["ORDINAL_POSITION"].ToString()),
				IsNull = (row["IS_NULLABLE"].ToString().ToUpper() == "TRUE"),
				TypeName = typeName,
				Length = length,
				DataScale = row["NUMERIC_SCALE"].ToString()
			});
		}
	}

	public override void FillingIndexs(List<IndexInfo>? info)
	{
	}

	public override void FillingRelations(List<RelationshipInfo>? info)
	{
	}

	public override void FillingViews(List<ViewInfo> info)
	{
	}

	public override void FillingProcs(List<ProcInfo> info)
	{
	}

	public override void FillingProcParams(List<ProcParamInfo> info)
	{
	}

	public override void FillingTypeInfos(List<TypeNameInfos> info)
	{
		DataTable schema = _mDbConnection.GetSchema("DataTypes");
		if (schema != null && schema.Rows.Count > 0)
		{
			info.AddRange(from DataRow row in schema.Rows
				select new TypeNameInfos
				{
					TypeName = row["TypeName"].ToString()
				});
		}
	}
}
